﻿
// TrafficPhaseDlg.cpp: 实现文件
//

#include "pch.h"
#include "framework.h"
#include "TrafficPhase.h"
#include "TrafficPhaseDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


CTrafficPhaseDlg::CTrafficPhaseDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_TRAFFICPHASE_DIALOG, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CTrafficPhaseDlg::DoDataExchange(CDataExchange* pDX){
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_CUSTOM1, m_paint);
	DDX_Control(pDX, IDC_CUSTOM2, m_graphShow);
	DDX_Control(pDX, IDC_EDIT3, m_infoOutput);
	DDX_Control(pDX, IDC_BUTTON1, m_PhaseButton);
	DDX_Control(pDX, IDC_BUTTON4, m_clearButton);
	DDX_Control(pDX, IDC_EDIT1, m_graphTips);
}

BEGIN_MESSAGE_MAP(CTrafficPhaseDlg, CDialogEx)
	ON_NOTIFY_EX(TTN_NEEDTEXT, 0, &CTrafficPhaseDlg::SetTipText)
	ON_WM_PAINT()
	ON_WM_PAINT(IDC_CUSTOM2,&CGraphShow::ShowGraph)
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_LINE, &CTrafficPhaseDlg::OnBnClickedLine)
	ON_BN_CLICKED(IDC_CONFLIT, &CTrafficPhaseDlg::OnBnClickedConflit)
	ON_BN_CLICKED(IDC_LINK, &CTrafficPhaseDlg::OnBnClickedLink)
	ON_WM_TIMER()
	ON_BN_CLICKED(IDC_BUTTON1, &CTrafficPhaseDlg::OnBnClickedButton1)
	ON_BN_CLICKED(IDC_BUTTON4, &CTrafficPhaseDlg::OnBnClickedButton4)
	ON_BN_CLICKED(IDC_CURSOR, &CTrafficPhaseDlg::OnBnClickedCursor)
END_MESSAGE_MAP()


// CTrafficPhaseDlg 消息处理程序

BOOL CTrafficPhaseDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时，框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	//允许鼠标停留
	EnableToolTips(TRUE);
	//重置窗口大小
	MoveWindow(INITSTARTX, INITSTARTY, INITWIDTH, INITHEIGHT, TRUE);

	//设置参数
	m_paint.firstClked = FALSE;
	m_paint.firstClkedLink = FALSE;
	return TRUE;  // 除非将焦点设置到控件，否则返回 TRUE
}

// 如果向对话框添加最小化按钮，则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序，
//  这将由框架自动完成。

void CTrafficPhaseDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CTrafficPhaseDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}



void CTrafficPhaseDlg::OnBnClickedCursor()
{
	// TODO: 在此添加控件通知处理程序代码
	m_paint.state = CURSORSTATE;
	//结束计时
	SetTimer(2, 30, NULL);
}

void CTrafficPhaseDlg::OnBnClickedLine()
{
	// TODO: 在此添加控件通知处理程序代码
	m_paint.state = LINESTATE;
	//结束计时
	KillTimer(2);
}

void CTrafficPhaseDlg::OnBnClickedLink()
{
	// TODO: 在此添加控件通知处理程序代码
	m_paint.state = LINKSTATE;
	//结束计时
	KillTimer(2);

}

void CTrafficPhaseDlg::OnBnClickedConflit()
{
	// TODO: 在此添加控件通知处理程序代码
	m_paint.state = CONFLICTSTATE;
	//结束计时
	KillTimer(2);
}

void CTrafficPhaseDlg::OnBnClickedButton1()
{
	//先结束计时
	KillTimer(2);
	// TODO: 在此添加控件通知处理程序代码
	trans();
	GraphVisual GV(nodeVisual, edgeVisualAll);
	GV.create();
	GV.showgraph();

	GV.paint();
	show(GV);
	m_graphShow.ShowGraph(GV);
	//在清空画布前不允许点击
	GetDlgItem(IDC_CURSOR)->EnableWindow(FALSE);
	GetDlgItem(IDC_LINE)->EnableWindow(FALSE);
	GetDlgItem(IDC_LINK)->EnableWindow(FALSE);
	GetDlgItem(IDC_CONFLICT)->EnableWindow(FALSE);
	GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);
}

void CTrafficPhaseDlg::OnBnClickedButton4()
{
	// TODO: 在此添加控件通知处理程序代码
	//结束计时
	KillTimer(2);

	//首先清空画布
	CBrush brush(RGB(255, 255, 255));
	CClientDC dc(&m_paint);
	CRect rectCtrl;
	m_paint.GetWindowRect(rectCtrl);
	this->ScreenToClient(rectCtrl);
	CRect nowCRet(CPoint(0, 0), CPoint(rectCtrl.Width(), rectCtrl.Height()));
	dc.FillRect(nowCRet, &brush);

	CBrush brush2(RGB(255, 255, 255));
	CClientDC dc2(&m_graphShow);
	CRect rectCtrl2;
	m_graphShow.GetWindowRect(rectCtrl2);
	this->ScreenToClient(rectCtrl2);
	CRect nowCRet2(CPoint(0, 0), CPoint(rectCtrl2.Width(), rectCtrl2.Height()));
	dc2.FillRect(nowCRet2, &brush2);

	//然后清空所有数据
	m_paint.lineArray.clear();
	m_paint.linkArray.clear();
	m_paint.conflictArray.clear();
	m_paint.linkPoint.clear();
	m_paint.linkArray.clear();
	m_paint.linkArray.clear();
	int tmpSize = m_paint.linkpointArray.size();
	for (int i = 0; i < tmpSize; i++) m_paint.linkpointArray[i].clear();
	m_paint.linkpointArray.clear();
	nodeVisual.clear();
	edgeVisualAll.clear();
	m_infoOutput.Clear();

	//然后把按钮复原
	GetDlgItem(IDC_CURSOR)->EnableWindow(TRUE);
	GetDlgItem(IDC_LINE)->EnableWindow(TRUE);
	GetDlgItem(IDC_LINK)->EnableWindow(TRUE);
	GetDlgItem(IDC_CONFLICT)->EnableWindow(TRUE);
	GetDlgItem(IDC_BUTTON1)->EnableWindow(TRUE);
}



BOOL CTrafficPhaseDlg::SetTipText(UINT id, NMHDR* pTTTStruct, LRESULT* pResult) {
	TOOLTIPTEXT* pTTT = (TOOLTIPTEXT*)pTTTStruct;
	UINT nID = pTTTStruct->idFrom;   //得到相应窗口ID，有可能是HWND
	if (pTTT->uFlags & TTF_IDISHWND) {
		nID = ::GetDlgCtrlID((HWND)nID);
		if (NULL == nID) return false;
		switch (nID) {
		case IDC_CURSOR:
			pTTT->lpszText = _T("Cursor用于悬停显示道路信息");
			return TRUE;
		case IDC_LINE:
			pTTT->lpszText = _T("Line用于绘制直线道路\n左键按下开始，左键抬起结束");
			return TRUE;
		case IDC_LINK:
			pTTT->lpszText = _T("Link用于绘制道路连接点\n左键在道路处按下开始，左键在道路处抬起结束");
			return TRUE;
		case IDC_CONFLICT:
			pTTT->lpszText = _T("Conflict用于添加道路连接点冲突\n左键分别按下选中两个Link，形成Conflict");
			return TRUE;
		case IDC_BUTTON1:
			pTTT->lpszText = _T("点击按钮进行相位计算\n灰色时不可点按");
			return TRUE;
		case IDC_BUTTON4:
			pTTT->lpszText = _T("点击按钮进行消除画布同时清空数据");
			return TRUE;
		}
		//if (m_paint.state == CURSORSTATE) {
		//	CRect rect;
		//	CPoint point;
		//	GetCursorPos(&point);//获取当前指针的坐标（注意，这是屏幕的） 
		//	m_paint.GetWindowRect(&rect);//获取客户区（客户区的左上角）相对于屏幕的位置  
		//	int pointX = (point.x - rect.left);//通过变换的到客户区的坐标  
		//	int pointY = (point.y - rect.top);
		//	CPoint cP(pointX, pointY);
		//	if (int ID = m_paint.inLine(cP) != -1) {
		//		CString cs;
		//		cs.Format(_T("Line 名：%s ， Line ID:%d"), m_paint.GetLineByID(ID).name, m_paint.GetLineByID(ID).ID);
		//		pTTT->lpszText = cs.AllocSysString();
		//		return TRUE;
		//	}
		//	else if (ID = m_paint.inLink(cP) != -1) {
		//		CString cs;
		//		cs.Format(_T("Link 名：%s ，Link ID:%d"), m_paint.GetLinkByID(ID).name, m_paint.GetLinkByID(ID).ID);
		//		pTTT->lpszText = cs.AllocSysString();
		//		return TRUE;
		//	}
		//}
	}
	return FALSE;
}

void CTrafficPhaseDlg::OnTimer(UINT_PTR nIDEvent) {
	CRect rect;
	CPoint point;
	GetCursorPos(&point);//获取当前指针的坐标（注意，这是屏幕的） 
	m_paint.GetWindowRect(&rect);//获取客户区（客户区的左上角）相对于屏幕的位置  
	int pointX = (point.x - rect.left);//通过变换的到客户区的坐标  
	int pointY = (point.y - rect.top);
	CPoint cP(pointX, pointY);
	int ID;
	ID = m_paint.inLine(cP);
	if (ID  != -1) {
		CString cs;
		cs.Format(_T("Line 名：%s ，Line ID:%d"), m_paint.GetLineByID(ID).name, ID);
		m_graphTips.SetWindowText(cs);
		return;
	}
	else {
		CRect rect;
		CPoint point;
		GetCursorPos(&point);//获取当前指针的坐标（注意，这是屏幕的） 
		m_paint.GetWindowRect(&rect);//获取客户区（客户区的左上角）相对于屏幕的位置  
		int pointX = (point.x - rect.left);//通过变换的到客户区的坐标  
		int pointY = (point.y - rect.top);
		CPoint cP(pointX, pointY);
		int ID;
		ID = m_paint.inLink(cP);
		if (ID != -1) {
			CString cs;
			cs.Format(_T("Link 名：%s ，Link ID:%d"), m_paint.GetLinkByID(ID).name, ID);
			m_graphTips.SetWindowText(cs);
			return;
		}
	}
	m_graphTips.SetWindowText(_T(""));
}



void CTrafficPhaseDlg::trans() {
	for (int i = 0; i < m_paint.linkArray.size(); i++) {
		CPoint cp(0, 0);
		nodeVisual.push_back(cp);
	}
	for (auto conflict : m_paint.conflictArray) {
		edgeVisual eV;
		eV.start = m_paint.GetLinkIndexByID(conflict.clFirst.ID);
		eV.end = m_paint.GetLinkIndexByID(conflict.clSecond.ID);
		edgeVisualAll.push_back(eV);
	}
}

void CTrafficPhaseDlg::show(GraphVisual& GV) {
	std::vector<int> phaseResult = GV.showcolor();
	//计算共有几个相位
	int phaseNum = 0;
	for (auto phase : phaseResult) {
		phase++;
		phaseNum = phase > phaseNum ? phase : phaseNum;
	}
	m_infoOutput.SetSel(-1, -1);
	CString cs;
	cs.Format(TEXT("共%d个相位\r\n每一个相位分别为：\r\n"), phaseNum);
	m_infoOutput.ReplaceSel(cs);
	//printf("共%d个相位\n每一个相位分别为：\n",phaseNum);

	for (int phaseNow = 0; phaseNow < phaseNum; phaseNow++) {

		m_infoOutput.SetSel(-1, -1);
		CString cs;
		cs.Format(TEXT("第%d相位为:"), phaseNow + 1);
		m_infoOutput.ReplaceSel(cs);

		//printf("第%d相位为：", phaseNow + 1);
		for (int j = 0; j < phaseResult.size(); j++) {
			if (phaseResult[j] == phaseNow) {
				m_infoOutput.SetSel(-1, -1);
				CString cs;
				cs.Format(TEXT("Link:%d "), j + 1);
				m_infoOutput.ReplaceSel(cs);
			}
		}
		m_infoOutput.SetSel(-1, -1);
		m_infoOutput.ReplaceSel(TEXT("；\r\n"));
	}

	for (int phaseNow = 0; phaseNow < phaseNum; phaseNow++) {
		CPen pen;
		switch (phaseNow) {
		case 0: pen.CreatePen(PS_SOLID, LINEWIDTH, RGB(0, 255, 0)); break;
		case 1: pen.CreatePen(PS_SOLID, LINEWIDTH, RGB(0, 0, 255)); break;
		case 2: pen.CreatePen(PS_SOLID, LINEWIDTH, RGB(255, 0, 255)); break;
		case 3: pen.CreatePen(PS_SOLID, LINEWIDTH, RGB(0, 199, 140)); break;
		case 4: pen.CreatePen(PS_SOLID, LINEWIDTH, RGB(128, 118, 105)); break;
		case 5: pen.CreatePen(PS_SOLID, LINEWIDTH, RGB(255, 255, 0)); break;
		case 6: pen.CreatePen(PS_SOLID, LINEWIDTH, RGB(128, 42, 42)); break;
		case 7: pen.CreatePen(PS_SOLID, LINEWIDTH, RGB(255, 0, 0)); break;
		case 8: pen.CreatePen(PS_SOLID, LINEWIDTH, RGB(255, 0, 255)); break;
		case 9: pen.CreatePen(PS_SOLID, LINEWIDTH, RGB(255, 215, 0)); break;
		}
		CClientDC dc(&m_paint);
		CPen* pOldPen = dc.SelectObject(&pen);

		for (int j = 0; j < phaseResult.size(); j++) {
			if (phaseResult[j] == phaseNow) {
				//接下来需要让Link变色啦
				for (int k = 0; k < m_paint.linkpointArray[j].size() - 1; k++) {
					CPoint cps = m_paint.linkpointArray[j][k];
					CPoint cpe = m_paint.linkpointArray[j][k + 1];
					dc.MoveTo(cps);
					dc.LineTo(cpe);
				}
				//同时，重绘一下箭头
				int i;
				for (i = m_paint.linkpointArray[j].size() / 3; i < 2 * m_paint.linkpointArray[j].size() / 3 - 1; i++) {
					//画线
					CPoint cpStart = m_paint.linkpointArray[j][i];
					CPoint cpEnd = m_paint.linkpointArray[j][i + 1];
					CClientDC dc(&m_paint);
					CPen pen(PS_SOLID, 3, RGB(255, 0, 0));
					dc.SelectObject(pen);
					dc.MoveTo(cpStart);
					dc.LineTo(cpEnd);
				}
				i--;//从这里开始绘制箭头的头部
				if (i >= m_paint.linkpointArray[j].size() / 3 + 1) {
					CPoint cpStart = m_paint.linkpointArray[j][i];
					//再取前一个点作为斜率
					CPoint cpStart_5 = m_paint.linkpointArray[j][i - 1];
					CPoint cpEnd1 = CPoint(
						(cpStart_5.x - cpStart.x) * cos(PI / 6) - (cpStart_5.y - cpStart.y) * sin(PI / 6) + cpStart.x,
						(cpStart_5.x - cpStart.x) * sin(PI / 6) + (cpStart_5.y - cpStart.y) * cos(PI / 6) + cpStart.y
					);
					CPoint cpEnd2 = CPoint(
						(cpStart_5.x - cpStart.x) * cos(-PI / 6) - (cpStart_5.y - cpStart.y) * sin(-PI / 6) + cpStart.x,
						(cpStart_5.x - cpStart.x) * sin(-PI / 6) + (cpStart_5.y - cpStart.y) * cos(-PI / 6) + cpStart.y
					);
					CClientDC dc(&m_paint);
					CPen pen(PS_SOLID, 3, RGB(255, 0, 0));
					dc.SelectObject(pen);
					dc.MoveTo(cpStart);
					dc.LineTo(cpEnd1);
					dc.MoveTo(cpStart);
					dc.LineTo(cpEnd2);
				}


			}
		}
		dc.SelectObject(pOldPen);
	}
}